#include <ctime>
#include <qapplication.h>
#include "window.moc"
#include "glwidget.h"
#include "ucdinputfile.h"
#include "visStreamline.h"

using namespace visualization;

double xmin, xmax, ymin, ymax, zmin, zmax;
double c[3];
double scale;

//vector<zeropoint> zeroPoint;

// This may be spacial for each file.
intgResults *results;

class glW: public GLWidget
{
public:
	glW(QWidget *parent = 0) 
	     : GLWidget(parent)
	{}
	~glW()
  {
	}

	GLuint makeObject();
};
class win : public Window
{
public:
	win(glW *glwidget)
		: Window(glwidget)
	{}
	~win(){}
};
void compute(string);
int main(int argc, char *argv[])
{
	compute(argv[1]);

  QApplication app(argc, argv);

 	c[0] = (xmax + xmin)/2;
	c[1] = (ymax + ymin)/2;
	c[2] = (zmax + zmin)/2;

	glW *glw = new glW();
	if(argc < 2)
	{
		cerr << "Input a data file please..." << endl;
		return 0;
	}
  win window(glw);
	window.generateWindow();
	window.show();
  app.exec();
	delete results;
	return 0;
}

void compute(string filename)
{
	Model t;
	UCDInputFile file(filename);

	file.FGetModel(t);	
	t.buildKDTree();
	t.getBound(xmin, xmax, ymin, ymax, zmin, zmax);

	cout << "Input the scale..." << endl;
	cin >> scale;

	visStreamline s(&t);
	cout << "Input the parameter file for streamline generation..." << endl;
	string pfile;
	cin >> pfile;
	s.parseParameter(pfile);

	cout << "Input the number of streamlines you want..." << endl;
	size_t num;
	cin >> num;

//
  Point *sources = new Point[num];
  double x, y, z;
  srand( (unsigned int)time(NULL) );
  for(unsigned int i = 0; i < num; i++)
  {
    x = rand()/double(RAND_MAX);
    y = rand()/double(RAND_MAX);
    z = rand()/double(RAND_MAX);
    
    x = xmin + ( xmax - xmin ) * x;
    y = ymin + ( ymax - ymin ) * y;
    z = zmin + ( zmax - zmin ) * z;
    
    sources[i].setCoordinates(x, y, z);
  }

//
//

//	while(cin >> num)
//	{
//		if(num > 10)
//			break;
//		else
//		{
//			cout << "Reinput please..." << endl;
//		}
//	}
//	if(abs(zmax - zmin) < 1e-6)
//	{
//		num = sqrt(num);
//	}
//	else
//	{
//		num = pow(num, 1.0/3);
//	}
//
//	int pN = 0;
//	if(abs(zmax - zmin) < 1e-6)
//	{
//		pN = num * num;
//	}
//	else
//	{
//		pN = num * num * num;
//	}
//
//	double xStp = (xmax - xmin)/(num-1);
//	double yStp = (ymax - ymin)/(num-1);
//
//  Point *sources = new visualization::Point[pN];
//
//	int indx = 0;
//	// If the data is 2D.
//	if( abs(zmax - zmin) < 1e-6 )
//	{
//		for(double i = xmin; i <= xmax; i+=xStp)
//		{
//			for(double j = ymin; j <= ymax; j+=yStp)
//			{
//				sources[indx].setCoordinates(i, j, 0);
//				indx++;
//			}
//		}
//	}
//	else
//	{
//		double zStp = (zmax - zmin)/(num-1);
//		for(double i = xmin; i <= xmax; i+=xStp)
//		{
//			for(double j = ymin; j <= ymax; j+=yStp)
//			{
//				for(double k = zmin; k <= zmax; k+=zStp)
//				{
//					sources[indx].setCoordinates(i, j, k);
//					indx++;
//				}
//			}
//		}
//	}
	s.setIntegrationDouble();
	s.setSources(sources, num);
	delete []sources;
	s.setParameters(0.5, 200);

	//zeroPoint = s.m_criticalPoints;

	time_t begin, end;
	begin = clock();
	results = s.integrate();
	end = clock();
	cout << "Time used : " << (double)(end - begin)/CLOCKS_PER_SEC << endl;
	
}
GLuint glW::makeObject()
{
	GLuint list = glGenLists(1);
	glNewList(list, GL_COMPILE);

	glBegin(GL_LINES);
	drawFramework(xmin-c[0], xmax-c[0], ymin-c[1], ymax-c[1], zmin-c[2], zmax-c[2], scale);
	glEnd();

	glEnable(GL_SMOOTH);
	glColor3f(0, 0, 0);
	glLineWidth(1.5);
	for(size_t i = 0; i < results->size(); i++)
	{
		glBegin(GL_LINE_STRIP);		
			for(size_t j = 0; j < (*results)[i].size(); j++)
				glVertex3f( ((*results)[i][j].getX()-c[0])/scale, ((*results)[i][j].getY()-c[1])/scale, 
									  ((*results)[i][j].getZ()-c[2])/scale);
		glEnd();
	}
//	glPointSize(4);
//	glBegin(GL_POINTS);
//	for(size_t i = 0; i < zeroPoint.size(); i++)
//	{
//		glVertex3f( (zeroPoint[i].position.getX() - c[0])/scale,
//								(zeroPoint[i].position.getY() - c[1])/scale,
//								(zeroPoint[i].position.getZ() - c[2])/scale
//							);
//
//	}
//	glEnd();

	glEndList();
	return list;
}
